// (项目源码)

/*日志系统：
    作用：将一条消息，进行格式化称为指定格式的字符串后，写入到指定位置
        1、日志要写入指定位置（标准输出，指定文件，滚动文件）
           日志系统需要支持将日志消息落地到不同的位置--多落地方向
        2、日志写入指定位置，支持不同的写入方式（同步，异步）
           同步：业务线程自己负责日志的写入（流程简单，但是有可能会因为阻塞导致效率降低
           异步：业务线程将日志放入缓冲区内存，让其他异步线程负责将日志写入指定位置
        3、日志输出以日志器为单位，支持多日志器（不同的项目组有不同的输出策略）
           日志器的管理
    模块划分：
        日志等级模块：枚举出日志分为多少个等级---对不同的日志有不同等级标记--以便于控制输出
        日志消息模块：封装一条日志所需的各种要素（时间、线程ID、文件名、行号、日志等级、消息主体...）
        消息格式化模块：按照指定的格式，对于日志消息关键要素进行组织，最终得到一个指定格式的字符串
                %d{%H:%M:%S}%T[%t]%T[%p]%T[%c]%T%f:%l%T%m%n
                [12:38:45] [12345678] [FATAL] [root] main.c:178 套接字创建失败...\n
        日志落地模块：负责对日志消息进行指定方向的写入输出
        日志器模块：对上边几个模块的整合
                日志限制输出等级、消息格式化模块对象、日志落地模块对象
                同步日志器模块---完成日志的同步输出功能
                异步日志器模块---完成日志的异步输出功能
        异步线程模块：负责异步日志的实际落地输出功能
        单例的日志器管理模块：对日志进行全局的管理，以便于能够在项目的任何位置获取指定的日志器进行日志输出
*/

/*实用工具类的实现：
    1、获取系统时间
    2、判断文件是否存在
    3、获取文件所在路径
    4、创建目录
*/

#ifndef __M__UTIL_H__
#define __M__UTIL_H__
#include <iostream>
#include <ctime>
#include <unistd.h>
#include <sys/stat.h>
namespace bitlog
{
    namespace util
    {
        class Date
        {
        public:
            static size_t now() // 获取当前系统时间
            {
                return (size_t)time(nullptr); // 定义一个静态成员接口，不用去实例化对象了，直接通过类名加上作用域限定符就可以直接访问这个接口
            }
        };
        class File
        {
        public:
            static bool exists(const std::string &pathname) // 判断文件是否存在
            {
                struct stat st;
                if (stat(pathname.c_str(), &st) < 0) // 通用的
                {
                    return false;
                }
                return true;

                // return (access(pathname.c_str(),F_OK)==0);//这是系统调用接口，只有Linux有用
            }
            static std::string path(const std::string &pathname) // 获取文件所在路径
            {
                // ./abc/bcd/a.txt
                // a.txt
                size_t pos = pathname.find_last_of("/\\"); // 查找/和\俩个字符中的任意一个字符
                if (pos == std::string::npos)
                    return "."; // 没找到，返回当前目录

                return pathname.substr(0, pos + 1); // 与/一起截取出来
            }

            static void createDirectory(const std::string &pathname) // 创建目录
            {
                // ./abc/bcd/a.txt
                size_t pos = 0, idx = 0;
                while (idx < pathname.size())
                {
                    pos = pathname.find_first_of("/\\", idx); // 从起始位置开始找【）

                    if (pos == std::string::npos) // 没有路径，直接创建目录
                    {
                        mkdir(pathname.c_str(), 0777);
                    }
                    std::string parent_dir = pathname.substr(0, pos + 1);
                    // if(parent_dir=="."||parent_dir=="..")
                    // {
                    //     idx = pos+1;
                    //     continue;
                    // }
                    if (exists(parent_dir) == true)
                    {
                        idx = pos + 1;
                        continue;
                    }
                    mkdir(parent_dir.c_str(), 0777);
                    idx = pos + 1;
                }
            }
        };
    }
}

// namespace bitlog
// {
//     namespace util
//     {
//         class Date
//         {
//         public:
//             static size_t getTime() //定义一个静态成员接口，不用去实例化对象了，直接通过类名加上作用域限定符就可以直接访问这个接口
//             {
//                 return (size_t)time(nullptr);
//             }
//         };
//         class File
//         {
//         public:
//             static bool exists(const std::string &pathname)
//             {
//                 return (access(pathname.c_str(),F_OK)==0)//这是系统调用接口，
//             }
//             static std::string path(const std::string &pathname);
//             static void createDirectory(const std::string &pathname);
//         };
//     }
// }

#endif